using System.Collections.Generic;
using System.Data;

using Lizk.SimpleHUD;
using System.IO;
using Lizk.WebScraper;
using System;
using SharpMedia.Controls;
using MediaData;

namespace SharpMedia.Pages
{
    public class GridTitleSelectionPage : MediaPage
    {
        private string currentType;
        private HUD2dList list;
        private HUDImage selection;
        private HUDImage offlineIcon;
        private HUDLabel offline, lblCount;
        private TimedTrigger<string> keyTrigger;
        private TripTrigger selectionTrigger = new TripTrigger(new TimeSpan(0, 0, 0, 0, 200));
        private bool showOffline = true;

        public GridTitleSelectionPage(MediaPage parent, string type)
            : base(parent)
        {
            currentType = type;
            InitializeComponents();
        }

        private void InitializeComponents()
        {
            selection = new HUDImage("bigselection.png");
            selection.MovementPattern = MovementPattern.DeltaBased;
            selection.MovementSpeed = 12f;
            selection.ConstrainProportions = false;
            selection.Size = new SizeS(400, 200);
            selection.Alpha = 0;
            Add(selection);

            list = new HUD2dList(new SizeS(350, 200));
            list.Bounds = new RectangleS(10, 100, Size.Width - 20, Size.Height - 110);
            list.Anchor = Anchor.All;
            Add(list);


            offline = new HUDLabel("Show offline", "tahoma14b");
            offline.Bounds = new RectangleS(34, 80, 170, 16);
            offline.Alignment = Alignment.VCenter;
            Add(offline);

            offlineIcon = new HUDImage(showOffline ? "yes.png" : "no.png");
            offlineIcon.Bounds = new RectangleS(offline.Bounds.Left - 20, offline.Bounds.Top, 16, 16);
            Add(offlineIcon);

            lblCount = new HUDLabel("", "tahoma30b");
            lblCount.Anchor = Anchor.Top | Anchor.Right;
            lblCount.Alignment = Alignment.Right | Alignment.VCenter;
            lblCount.Location = new PointS(Bounds.Right - 200, 0);
            lblCount.Size = new SizeS(180, list.Bounds.Top - 20);
            Add(lblCount);


            keyTrigger = new TimedTrigger<string>("", new TimeSpan(0, 0, 0, 0, 600));
            keyTrigger.TimeOut += new EventHandler(keyTrigger_TimeOut);
            keyTrigger.FirstTrigger += new EventHandler(keyTrigger_FirstTrigger);
            keyTrigger.ReTriggered += new EventHandler(keyTrigger_ReTriggered);

            selectionTrigger.TimeOut += new EventHandler(selectionTrigger_TimeOut);

            list.SelectedIndexChanged += new EventHandler<SelectionEventArgs>(list_SelectedIndexChanged);
        }

        void list_SelectedIndexChanged(object sender, SelectionEventArgs e)
        {
            selectionTrigger.Trigger();
            if (list.Count > 0)
            {
                list.Get<GridPageItem>(e.OldIndex).OfflineLabel.Fade(0, 6f);
                RectangleS selectionBounds = new RectangleS(new PointS(list.Bounds.Left + list.Selection.Left, list.Bounds.Top + list.Selection.Top), list.Selection.Size);

                selection.Destination = selectionBounds.Location;
                selection.DestinationSize = selectionBounds.Size;


                selection.Fade(255, 6f);

                if (!e.Animate)
                {
                    selection.Size = selection.DestinationSize;
                    selection.Location = selection.Destination;
                    selection.Alpha = 255;
                }
                lblCount.Text = list.SelectedIndex + 1 + " of " + list.Count;
                //list_SelectedIndexChanged(this, new SelectionEventArgs(list.SelectedIndex, false));

            }
            else
            {
                lblCount.Text = "No items found";
                selection.Alpha = 0;
            }

        }

        void selectionTrigger_TimeOut(object sender, EventArgs e)
        {
            if (list.GetSelectedControl<GridPageItem>() == null)
                return;

            if (Util.IsTitleOffline(SelectedTitle()))
            {
                list.GetSelectedControl<GridPageItem>().OfflineLabel.Fade(255, 6f);
            }
        }


        void keyTrigger_ReTriggered(object sender, EventArgs e)
        {
            SelectByString(keyTrigger.StateVar);
        }

        void keyTrigger_FirstTrigger(object sender, EventArgs e)
        {
            SelectByString(keyTrigger.StateVar);
        }

        void keyTrigger_TimeOut(object sender, EventArgs e)
        {
            keyTrigger.Reset("");
        }

        public override void Update(TimeSpan ts)
        {
            base.Update(ts);
            keyTrigger.Update();
            selectionTrigger.Update(ts);
        }

        public void SelectByString(string s)
        {
            int i = 0;
            if (s.Length == 0)
                return;

            while (i < list.Count && s.CompareTo(list.Get<GridPageItem>(i).Title.Name) > -1)
            {

                i++;
            }


            if (i == list.Count)
                return;
            if (s.ToLower()[0].CompareTo(list.Get<GridPageItem>(i).Title.Name.ToLower()[0]) < 0 && i > 0)
            {
                i--;
            }
            list.SelectedIndex = i;
            UpdateSelection(true);
        }


        protected override void MediaChanged(MediaDataSet changes)
        {
            
            for (int i = 0; i < list.Count; i++)
            {
                GridPageItem gi = list.Get<GridPageItem>(i);
                if (gi.Title.RowState == DataRowState.Deleted || gi.Title.RowState == DataRowState.Detached || gi.Title.GetFilesRows().Length == 0)
                {
                    list.RemoveAt(i--);
                    continue;
                }
                if (Util.IsTitleOffline(gi.Title))
                {
                    if (!showOffline)
                    {
                        list.RemoveAt(i--);
                        continue;
                    }
                    else
                    {
                        gi.Image.Color = ColorS.Red;
                        gi.OfflineLabel.Text = Util.PrintVolumeInfo(gi.Title) + "\nIs unavailable!";
                    }
                }
                else
                {
                    gi.Image.Color = ColorS.White;
                    gi.OfflineLabel.Fade(0, 6f);
                }

                gi.Image.File = SharpMedia.ImageCache.TryGetImagePath(gi.Title, "film.png");
            }
            
            int insertIndex = 0;
            
            foreach (MediaDataSet.TitlesRow title in (from t in SharpMedia.Database.Data.Titles where t.Type == currentType orderby t.Name select t))
            {
                if (title.RowState == DataRowState.Deleted || (Util.IsTitleOffline(title) && !showOffline))
                    continue;
                insertIndex = InsertTitle(insertIndex, title);
            }
            list.MoveItems(true);
            UpdateSelection(true);
        }

        private int InsertTitle(int i, MediaDataSet.TitlesRow title)
        {
            while (i < list.Count && title.Name.CompareTo(list.Get<GridPageItem>(i).Title.Name) > -1)
            {
                if (list.Get<GridPageItem>(i).Title == title)
                    return i;
                i++;
            }
            GridPageItem item = new GridPageItem(title, list.ItemSize);
            item.OnMouseUp += new EventHandler<MouseEventArgs>(item_OnMouseUp);
            //item.SetScraperIcon(SharpMedia.ScraperCache.GetScrapeStatus(title));
            
            list.Insert(i, item);
            return i;
        }

        void item_OnMouseUp(object sender, HUDControl.MouseEventArgs e)
        {
            int index = list.IndexOf((HUDControl)sender);
            if (index > -1)
            {
                if (list.SelectedIndex == index)
                {
                    Command(HUDCommands.Select, null);
                }
                else
                {
                    list.SelectedIndex = index;
                }
            }
        }

        private void ListItems()
        {
            string currentTitle = null;

            var titles = from t in SharpMedia.Database.Data.Titles
                         where t.Type == currentType && t.GetFilesRows().Length > 0
                         orderby t.Name
                         select t;

            if (list.GetSelectedControl<GridPageItem>() != null)
            {
                currentTitle = list.GetSelectedControl<GridPageItem>().TitleLabel.Text;
            }        

            list.Clear();
            foreach (var title in titles)
            {
                if (!showOffline && Util.IsTitleOffline(title))
                    continue;
                GridPageItem item = new GridPageItem(title, list.ItemSize);
                item.OnMouseUp += new EventHandler<MouseEventArgs>(item_OnMouseUp);
                list.Add(item);
            }

            list.MoveItems(false);
            if (currentTitle != null)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    int cmp = list.Get<GridPageItem>(i).TitleLabel.Text.CompareTo(currentTitle);
                    if (cmp < 1)
                    {
                        list.SelectedIndex = i;
                        if (cmp == 0)
                            break;
                    }
                }
                UpdateSelection(true);
            }
            else
            {
                UpdateSelection(false);
            }
        }


        private void UpdateSelection(bool animate)
        {
            list_SelectedIndexChanged(this, new SelectionEventArgs(list.SelectedIndex, animate));
        }



        public override void Activate()
        {
            Fade(255, 6f);
            base.Activate();
        }

        public override void Show()
        {
            lock(SharpMedia.UpdateLockObject)
                if(!SharpMedia.UpdateLock)
                    ListItems();

            Fade(255, 6f);

            base.Show();
        }

        public override void Close()
        {
            Fade(0, 6f);
            base.Close();
        }

        public override void Deactivate()
        {
            Fade(0, 6f);
            base.Deactivate();
        }


        public MediaDataSet.TitlesRow SelectedTitle()
        {
            if (list.Count == 0 || list.SelectedIndex < 0)
                return null;

            return list.GetSelectedControl<GridPageItem>().Title;
        }


        public override void ResizeMove(RectangleS oldRect, RectangleS newRect)
        {
            base.ResizeMove(oldRect, newRect);
            if (list != null)
                UpdateSelection(true);
        }

        public override void Command(HUDCommands command, object tag)
        {
            MediaDataSet.TitlesRow title = SelectedTitle();
            switch (command)
            {
                case HUDCommands.Up:
                    list.SelectedRow--;
                    break;
                case HUDCommands.Down:
                    list.SelectedRow++;
                    break;
                case HUDCommands.Left:
                    list.SelectedColumn--;
                    break;
                case HUDCommands.Right:
                    list.SelectedColumn++;
                    break;
                case HUDCommands.PageUp:
                    list.SelectedRow -= 10;
                    break;
                case HUDCommands.PageDown:
                    list.SelectedRow += 10;
                    break;
                case HUDCommands.Back:
                    if (keyTrigger.Triggered)
                        break;
                    SharpMedia.Back();
                    break;
                case HUDCommands.Menu:
                    if (keyTrigger.Triggered)
                        break;
                    showOffline = !showOffline;
                    offlineIcon.File = showOffline ? "images/yes.png" : "images/no.png";
                    if (SharpMedia.CanUseDatabase)
                        ListItems();
                    break;
                case HUDCommands.Web:
                    if (title == null)
                        break;
                    if (keyTrigger.Triggered)
                        break;

                    Util.TryScrape(this, SelectedTitle());
                    break;
                
                case HUDCommands.Select:
                    if (title == null)
                        break;

                    if(!SharpMedia.CanUseDatabase)
                        return;

                    RectangleS selectedItemBounds = new RectangleS(list.GetSelectedControl<GridPageItem>().Image.Bounds.Location + list.SelectedControl.Bounds.Location + list.Bounds.Location, list.GetSelectedControl<GridPageItem>().Image.Size);

                    var episodes = title.GetEpisodesRows();

                    if (episodes.Length > 0)
                    {
                        EpisodeSelectionPage esp = new EpisodeSelectionPage(this, title, selectedItemBounds, list.GetSelectedControl<GridPageItem>().Image.ImageSize.Size, null);
                        SharpMedia.Navigate(esp);
                    }
                    else
                    {

                        MovieInfoPage mip = new MovieInfoPage(this, title);
                        SharpMedia.Navigate(mip);
                        Fade(0, 6f);

                    }
                    break;
                case HUDCommands.KeyPress:
                    if (keyTrigger.StateVar.Trim() == "" && (char)tag == ' ')
                    {

                    }
                    else
                        keyTrigger.StateVar += (char)tag;
                    break;
                default:
                    if (parent != null)
                        parent.Command(command, tag);
                    break;
            }
        }

    }

    public class GridPageItem : HUDContainerSimple
    {
        private MediaDataSet.TitlesRow title;
        private HUDImage image;
        private ScraperIcon scraperImage;
        private HUDLabel offlineLabel;
        private HUDLabel titleLabel;
        private HUDImage backSelection;

        public HUDLabel TitleLabel
        {
            get { return titleLabel; }
            set { titleLabel = value; }
        }

        public HUDLabel OfflineLabel
        {
            get { return offlineLabel; }
            set { offlineLabel = value; }
        }

        public ScraperIcon ScraperImage
        {
            get { return scraperImage; }
            set { scraperImage = value; }
        }

        public HUDImage Image
        {
            get { return image; }
            set { image = value; }
        }

        public MediaDataSet.TitlesRow Title
        {
            get { return title; }
            set { title = value; }
        }

        public HUDImage BackSelection
        {
            get { return backSelection; }
            set { backSelection = value; }
        }

        public GridPageItem(MediaDataSet.TitlesRow title, SizeS itemSize)
        {
                this.title = title;    
                Size = itemSize;

                backSelection = new HUDImage("bigselection.png");
                backSelection.MovementSpeed = 8f;
                backSelection.ConstrainProportions = false;
                backSelection.Size = Size;
                BackSelection.Anchor = Anchor.All;
                backSelection.Alpha = 0;
                Add(backSelection);


                image = new HUDImage(SharpMedia.ImageCache.TryGetImagePath(title, "film.png"));
                image.Bounds = new RectangleS(5, 15, itemSize.Width - 10, itemSize.Height - 40);
                image.Anchor = Anchor.All;
                image.Color = Util.IsTitleOffline(title) ? Lizk.SimpleHUD.ColorS.Red : Lizk.SimpleHUD.ColorS.White;
                image.FadeOnLoad = true;
                image.ImageSizeChanged += new EventHandler(image_ImageSizeChanged);
                Add(image);

                RectangleS s = HUDImage.ResizeConstrained(true, Image.ImageSize.Size, Image.Size);

                scraperImage = new ScraperIcon(title);
                scraperImage.Bounds = new RectangleS(image.Bounds.Left + s.Right - 42, Image.Bounds.Top + s.Bottom - 42, 42, 42);
                scraperImage.Anchor = Anchor.Bottom | Anchor.Right;
                Add(scraperImage);

                offlineLabel = new HUDLabel(Util.PrintVolumeInfo(title) + "\nIs unavailable!", "tahoma20b");
                offlineLabel.Alignment = Alignment.Center | Alignment.VCenter;
                offlineLabel.Bounds = new RectangleS(0, 0, itemSize.Width, itemSize.Height);
                offlineLabel.Alpha = 0;
                offlineLabel.Anchor = Anchor.All;
                Add(offlineLabel);

                titleLabel = new HUDLabel(title.Name, "tahoma28bo");
                titleLabel.Bounds = new RectangleS(5, image.Bounds.Bottom - 20, itemSize.Width - 10, itemSize.Height - image.Bounds.Bottom + 20);
                titleLabel.Alignment = Alignment.Center | Alignment.Bottom;
                titleLabel.Anchor = Anchor.All ^ Anchor.Top;
                Add(titleLabel);
        }

        public override void Update(TimeSpan ts)
        {
            base.Update(ts);

            if (!SharpMedia.Engine.IsCursorHidden && IsMouseOver)
            {
                backSelection.Fade(100, 6f);
            }
            else
            {
                backSelection.Fade(0, 6f);
            }

        }


        void image_ImageSizeChanged(object sender, EventArgs e)
        {
            RectangleS s = HUDImage.ResizeConstrained(true, Image.ImageSize.Size, Image.Size);
            scraperImage.Bounds = new RectangleS(image.Bounds.Left + s.Right - 42, Image.Bounds.Top + s.Bottom - 42, 42, 42);
        }


    }

    
}